// ml:run = $bin < input
#include <iostream>
#include <vector>
#include <queue>

int const maxn = 3000;
bool vis[maxn];
int a[maxn][maxn];
int b[maxn][maxn];
int n;

struct edge { int from, to, cost; };

bool operator<(edge const& a, edge const& b)
{
    return a.cost > b.cost;
}

bool check()
{
    for (int i = 0; i < n; i++)
        if (a[i][i]) return false;
    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            if (a[i][j] != a[j][i]) return false;
    return true;
}

bool equal()
{
    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++)
            if (a[i][j] != b[i][j]) return false;
    return true;
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++) std::cin >> a[i][j];

    if (!check()) { std::cout << "NOT MAGIC\n"; return 0; }

    std::priority_queue<edge> pq;
    vis[0] = true;
    for (int i = 1; i < n; i++)
        pq.push({0, i, a[0][i]});

    for (int i = 1; i < n; i++) {
        while (!pq.empty() && vis[pq.top().to]) pq.pop();
        if (pq.empty()) break;
        auto now = pq.top(); pq.pop();
        vis[now.to] = true;
        for (int j = 0; j < n; j++) {
            if (j == now.to) continue;
            if (vis[j]) {
                b[j][now.to] = b[now.to][j] =
                    std::max(b[j][now.from], now.cost);
            } else {
                pq.push({now.to, j, a[now.to][j]});
            }
        }
    }

    if (equal())
        std::cout << "MAGIC\n";
    else
        std::cout << "NOT MAGIC\n";
}

